!function () {
    'use strict';
    
    if (!(jQuery in window)) {
        throw new Error("File encrypt depends on jquery!");
    }
    var checksum;
    if (window.CryptoJS) {
        checksum = window.CryptoJS;
    } else {
        throw new Error("md5 encryption depends on CryptoJS!");
    }

    var old = $.fn.md5;
    
    $.support.fileApi=window.File && window.FileReader && window.FileList && window.Blob;
    
    $.fn.extend({
        "md5": function (done) {
            if (!this.is(":file")) {
                return checksum.MD5(_value(this));
            }
            if (!$.isFunction(done)) {
                throw new Error("A callback is needed to echo encrypt result!");
            }
            return this.each(function () {
                var file = this.files[0];
                var blob;
                var md5 = checksum.algo.MD5.create();
                var reader = new FileReader();
                var read = 0, unit = 1048576;
                reader.onload = function (e) {
                    var bytes = checksum.lib.WordArray.create(e.target.result);
                    md5.update(bytes);
                    read += unit;
                    if (read < file.size) {
                        blob = file.slice(read, read + unit);
                        reader.readAsArrayBuffer(blob);
                    } else {
                        var hash = md5.finalize();
                        done.call(e.target, hash.toString(checksum.enc.Hex));
                    }
                };

                reader.readAsArrayBuffer(file.slice(read, read + unit));
            });
        }
    });

    // MD5 NO CONFLICT
    // ====================
    $.fn.md5.noConflict = function () {
        $.fn.md5 = old;
        return this;
    };


    function _value() {
        var $element = arguments[0];
        var value = arguments[1];
        if (value === undefined || value === null) {
            return _getValue($element);
        } else {
            _setValue($element, value);
            return undefined;
        }
        function _getValue($j) {
            if ($j.is(":input")) {
                return $j.val();
            } else if ($j.is("img")) {
                return $j.attr("src");
            } else {
                return $j.html();
            }
        }
        function _setValue($j, value) {
            if ($j.is(":input")) {
                $j.val(value);
            } else if ($j.is("img")) {
                $j.attr("src", value);
            } else {
                $j.html(value);
            }
        }
    }
};